package com.yykj.bank.server.service.impl;

import com.yykj.bank.client.dto.BankInfoDTO;
import com.yykj.bank.client.form.BankInfoSearchForm;
import com.yykj.bank.server.converter.BankInfoDTOConverter;
import com.yykj.bank.server.model.entity.BankInfo;
import com.yykj.bank.server.model.repository.BankInfoRepository;
import com.yykj.bank.server.service.BankInfoService;
import com.yykj.common.util.LocalObjectUtil;
import com.yykj.common.util.PageRequestUtil;
import com.yykj.common.vo.PageData;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Service
public class BankInfoServiceImpl implements BankInfoService {
    @Override
    public List<BankInfoDTO> listAvailableBank() {
        List<BankInfo> list = bankInfoRepository.findAllByStatus(Boolean.TRUE);
        return BankInfoDTOConverter.convert(list);
    }

    @Override
    public BankInfoDTO editBankInfo(BankInfoDTO info) {
        BankInfo bankInfo = bankInfoRepository.findById(info.getCode()).orElse(null);
        if (bankInfo == null) {
            bankInfo = new BankInfo();
        }
        LocalObjectUtil.copyNullValue(info, bankInfo);
        bankInfoRepository.save(bankInfo);
        BeanUtils.copyProperties(bankInfo, info);
        return info;
    }

    @Override
    public PageData<BankInfo> searchBankInfo(BankInfoSearchForm bankInfoSearchForm) {
        PageRequest pageRequest = PageRequest.of(PageRequestUtil.getPage(bankInfoSearchForm.getCurrentPage())
                ,PageRequestUtil.getSize(bankInfoSearchForm.getPageSize()));
        Page<BankInfo> all = bankInfoRepository.findAll(generateSpecification(bankInfoSearchForm), pageRequest);
        return  PageData.formatList(all, bankInfoSearchForm.getCurrentPage(), bankInfoSearchForm.getPageSize());

    }

    @Override
    public void deleteBankInfo(String code) {
        bankInfoRepository.deleteById(code);
    }

    private Specification<BankInfo> generateSpecification(BankInfoSearchForm bankInfoSearchForm) {
        return new Specification<BankInfo>() {
            @Override
            public Predicate toPredicate(Root<BankInfo> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (!StringUtils.isEmpty(bankInfoSearchForm.getCode())) {
                    predicateList.add(builder.like(root.get("code"), "%" + bankInfoSearchForm.getCode() + "%"));
                }
                if (!StringUtils.isEmpty(bankInfoSearchForm.getName())) {
                    predicateList.add(builder.like(root.get("name"), "%" + bankInfoSearchForm.getName() + "%"));
                }
                if(bankInfoSearchForm.getStatus() !=null){
                    predicateList.add(builder.equal(root.get("status"), bankInfoSearchForm.getStatus()));
                }
                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        };
    }


    private BankInfoRepository bankInfoRepository;

    @Autowired
    public void setBankInfoRepository(BankInfoRepository bankInfoRepository) {
        this.bankInfoRepository = bankInfoRepository;
    }
}
